#include "preHeader.h"
#include "PacketDispatcher.h"
#include "Guild/GuildMgr.h"
#include "Rank/RankMgr.h"
#include "Operating/OperatingActivityMgr.h"
#include "Session/GameServerMgr.h"

enum PacketDispatcherProtocol
{
	CPDP_NONE,
	CPDP_RPC_INVOKE_2_GUILD,
	CPDP_RPC_INVOKE_2_RANK,
	CPDP_RPC_INVOKE_2_OPERATING,
	CPDP_RPC_REPLY,
};

PacketDispatcher::PacketDispatcher()
{
	RPCActor::SetReady(true);
}

PacketDispatcher::~PacketDispatcher()
{
}

void PacketDispatcher::Tick()
{
	mgr_.TickObjs();
}

void PacketDispatcher::SendPacket2Guild(const INetPacket &pck)
{
	sGuildMgr.PushRecvPacket(IServerService::NewServerPacket(pck.Clone()));
}

void PacketDispatcher::SendPacket2Rank(const INetPacket &pck)
{
	sRankMgr.PushRecvPacket(IServerService::NewServerPacket(pck.Clone()));
}

void PacketDispatcher::SendPacket2Operating(const INetPacket &pck)
{
	sOperatingActivityMgr.PushRecvPacket(IServerService::NewServerPacket(pck.Clone()));
}

void PacketDispatcher::RPCInvoke2Guild(const INetPacket &pck,
	const std::function<void(INetStream&, int32, bool)> &cb,
	AsyncTaskOwner *owner, time_t timeout)
{
	NetPacket trans(CPDP_RPC_INVOKE_2_GUILD);
	RPCTransInvoke(trans, pck, cb, owner, timeout);
}

void PacketDispatcher::RPCInvoke2Rank(const INetPacket &pck,
	const std::function<void(INetStream&, int32, bool)> &cb,
	AsyncTaskOwner *owner, time_t timeout)
{
	NetPacket trans(CPDP_RPC_INVOKE_2_RANK);
	RPCTransInvoke(trans, pck, cb, owner, timeout);
}

void PacketDispatcher::RPCInvoke2Operating(const INetPacket &pck,
	const std::function<void(INetStream&, int32, bool)> &cb,
	AsyncTaskOwner *owner, time_t timeout)
{
	NetPacket trans(CPDP_RPC_INVOKE_2_OPERATING);
	RPCTransInvoke(trans, pck, cb, owner, timeout);
}

void PacketDispatcher::RPCReply(
	const INetPacket &pck, uint64 sn, int32 err, bool eof)
{
	NetPacket trans(CPDP_RPC_REPLY);
	RPCTransReply(trans, pck, sn, err, eof);
}

void PacketDispatcher::PushRPCPacket(const INetPacket &trans,
	const INetPacket &pck, const std::string_view &args)
{
	INetPacket* pkt = pck.Clone();
	pkt->Append(args.data(), args.size());
	switch (trans.GetOpcode()) {
	case CPDP_RPC_INVOKE_2_GUILD:
		sGuildMgr.PushRecvPacket(IServerService::NewServerPacket(pkt));
		break;
	case CPDP_RPC_INVOKE_2_RANK:
		sRankMgr.PushRecvPacket(IServerService::NewServerPacket(pkt));
		break;
	case CPDP_RPC_INVOKE_2_OPERATING:
		sOperatingActivityMgr.PushRecvPacket(IServerService::NewServerPacket(pkt));
		break;
	case CPDP_RPC_REPLY:
		mgr_.OnRPCReply(pkt);
		break;
	default:
		assert(false && "can't reach here.");
		delete pkt;
		break;
	}
}

void PacketDispatcher::RunS2SRPCReply(SocialRPCReply replyType,
	const INetPacket &rpcRespPck, uint64 sn, int32 err, bool eof)
{
	switch ((SocialRPCReply)replyType) {
	case SocialRPCReply::GameServer:
		sGameServerMgr.RPCReply2GS(rpcRespPck, sn, eof);
		break;
	case SocialRPCReply::Guild:
	case SocialRPCReply::Rank:
	case SocialRPCReply::Operating:
		sPacketDispatcher.RPCReply(rpcRespPck, sn, eof);
		break;
	default:
		assert(false && "can't reach here.");
		break;
	}
}
